home *** CD-ROM | disk | FTP | other *** search
- /*
- File: USB_ManualEjectSupport.c
-
- Contains: All support for handling manual ejectable media.
-
- Version: 1.0
-
- Copyright: © 1999-2000 by Apple Computer, Inc., all rights reserved.
- */
-
- #include "USB_ManualEjectSupport.h"
-
- #include <DriverServices.h>
-
- #include "USB_ShimServicesSupport.h"
- #include "USB_StdCommands.h"
- #include "StorageDeviceConfiguration.h"
-
- extern UInt8 gDeviceUSBSubClass;
-
- #pragma mark --
- #pragma mark Manual Eject Check
-
- Boolean IsDeviceKnownManualEject( void )
- {
- Boolean result;
-
- if ( gDeviceUSBSubClass == kUSBStorageUFISubclass )
- {
- result = true;
- }
- else
- {
- // Get this information from the Device Info header
- result = kDeviceIsManualEject;
- }
-
- return result;
- }
-
- // These are all routines for handling the Manual Eject Check
- static Boolean MaintainManualEjectInterrupt = false;
- static Boolean gManualEjectRemoveIssued = false;
- static volatile Boolean InManualEjectCheckInterrupt = false;
- static TimerID ManualEjectInterruptTimer = 0;
- static OSStatus ManualEjectCheckInterrupt( void *p1, void *p2);
-
- // Accessors for Manual Eject Media Removed
- Boolean WasManualEjectRemoveIssued( void )
- {
- return gManualEjectRemoveIssued;
- }
-
- void SetManualEjectRemoveIssued( void )
- {
- gManualEjectRemoveIssued = true;
- }
-
- void ClearManualEjectRemoveIssued( void )
- {
- gManualEjectRemoveIssued = false;
- }
-
- // Accessors for In Manual Eject Interrupt flag
- void SetInManualEjectCheckInterrupt( void )
- {
- InManualEjectCheckInterrupt = true;
- }
-
- void ClearInManualEjectCheckInterrupt( void )
- {
- InManualEjectCheckInterrupt = false;
- }
-
- // Accessors for turning the manual eject check on and off
- Boolean GetMaintainManualEjectInterrupt( void )
- {
- return MaintainManualEjectInterrupt;
- }
-
- void SetManualCheckInterrupt( void )
- {
- gManualEjectRemoveIssued = false;
- MaintainManualEjectInterrupt = true;
- ResetManualEjectInterrupt();
- }
-
- void ClearManualEjectInterrupt( void )
- {
- MaintainManualEjectInterrupt = false;
- CancelManualEjectInterrupt();
- }
-
- void ResetManualEjectInterrupt( void )
- {
- AbsoluteTime theWait;
-
- // If there is an outstanding timer, cancel it
- CancelManualEjectInterrupt();
-
- // If we are maintaining an interrupt, set it now
- if (( MaintainManualEjectInterrupt == true ) && (InManualEjectCheckInterrupt == false))
- {
- // This is set to 5 seconds to collision problems with
- // commands that occur during hot-unplugging. This is only
- // a temporary fix and should be redesigned for Greyhound 1.4
- /* theWait = DurationToAbsolute(durationSecond*5);*/
- theWait = DurationToAbsolute(durationSecond);
- theWait = AddAbsoluteToAbsolute(UpTime(), theWait);
- SetInterruptTimer( &theWait, &ManualEjectCheckInterrupt, nil, &ManualEjectInterruptTimer);
- }
- }
-
- void CancelManualEjectInterrupt( void )
- {
- if( ManualEjectInterruptTimer != nil )
- {
- AbsoluteTime timeLeft;
-
- // Cancel any pending timers
- CancelTimer( ManualEjectInterruptTimer, &timeLeft);
- ManualEjectInterruptTimer = 0;
- }
- }
-
- enum
- {
- kEjectCheckStartState = 0,
- kEjectCheckTURDone,
- kEjectCheckReqSenseDone
- };
-
- static void ManualEjectCheckStateMachine( IntDriveRequestPBPtr requestPB );
-
- OSStatus ManualEjectCheckInterrupt( void *p1, void *p2)
- {
- #pragma unused ( p1, p2 )
- IntDriveRequestPB *ourPB;
-
- ManualEjectInterruptTimer = 0;
-
- if ( MaintainManualEjectInterrupt == false )
- {
- return noErr;
- }
-
- if ( IsCommandPending() == false )
- {
- // Only perform the check when there is no command pending
- ourPB = GetManualEjectPB();
- if ( ourPB == nil )
- {
- ResetManualEjectInterrupt();
- return noErr;
- }
-
- ourPB->currentExecutionState = kEjectCheckStartState;
- ourPB->completionProc = &ManualEjectCheckStateMachine;
- ManualEjectCheckStateMachine( ourPB );
- }
- else
- {
- ResetManualEjectInterrupt();
- }
-
- return noErr;
- }
-
- void ManualEjectCheckStateMachine( IntDriveRequestPBPtr requestPB )
- {
- OSStatus err = requestPB->status;
- Boolean resetTheInterrupt = false;
-
- if ( MaintainManualEjectInterrupt == false )
- {
- FreeManualEjectPB( requestPB );
- return;
- }
-
- switch( requestPB->currentExecutionState )
- {
- case kEjectCheckStartState:
- {
- // Let's do a TUR and Request sense to make sure the drive is in
- // a good state
- InManualEjectCheckInterrupt = true;
- requestPB->currentExecutionState = kEjectCheckTURDone;
- requestPB->completionProc = &ManualEjectCheckStateMachine;
- err = TestUnitReadyBuilder( requestPB );
- }
- break;
-
- case kEjectCheckTURDone:
- {
- requestPB->currentExecutionState = kEjectCheckReqSenseDone;
- requestPB->completionProc = &ManualEjectCheckStateMachine;
- err = RequestSenseBuilder( requestPB, (Ptr) requestPB->buffer );
- }
- break;
-
- case kEjectCheckReqSenseDone:
- {
- if ( err == noErr )
- {
- if((requestPB->buffer[12] == 0x28) || (requestPB->buffer[12] == 0x3A))
- {
- // The Disk has been removed, ask for it back
- gManualEjectRemoveIssued = true;
- InManualEjectCheckInterrupt = false;
- FreeManualEjectPB( requestPB );
- CancelManualEjectInterrupt();
- SendMediaWasRemovedEvent();
- return;
- }
- }
-
- // Reset the Interrupt
- resetTheInterrupt = true;
- }
- break;
- }
-
- if (( resetTheInterrupt == true ) || (err != kRequestPending))
- {
- FreeManualEjectPB( requestPB );
- InManualEjectCheckInterrupt = false;
- ResetManualEjectInterrupt();
- }
- }
-
-